#include "./PORT/port.h"
#include "../System/config.h"
#include "./BSP/DEBUG/debug.h"

#ifndef NULL
#define NULL ((void *)0)
#endif

void (*g_timx_callback_funs[20])(void);
uint16_t g_bitmx_callback_funs_time[20];
uint8_t g_bitmx_callback_funs_num = 0;

/**
 * @brief       基本定时器TIMX定时中断初始化函数
 * @note
 *              基本定时器的时钟来自APB1,当PPRE1 ≥ 2分频的时候
 *              基本定时器的时钟为APB1时钟的2倍, 而APB1为42M, 所以定时器时钟 = 84Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值。
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void btimx_int_init(uint8_t tim_id, uint16_t arr, uint16_t psc)
{
    TIM_TypeDef *timx;
    uint8_t irqn;

    if (tim_id == 6)
    {
        RCC->APB1ENR |= 1 << 4;
        timx = TIM6;
        irqn = TIM6_DAC_IRQn; // TIM6 is often used for DAC, but can be used for general purposes
    }

    timx->ARR = arr;              /* 设定计数器自动重装值 */
    timx->PSC = psc;              /* 设置预分频器  */
    timx->DIER |= 1 << 0;         /* 允许更新中断 */
    timx->CR1 |= 1 << 0;          /* 使能定时器TIMX */
    sys_nvic_init(2, 3, irqn, 2); /* 抢占1，子优先级3，组2 */
}

/**
 * @brief       基本定时器TIMX定时中断回调函数注册
 * @param       callback: 定时器中断回调函数
 * @param       time: 执行时间间隔 单位ms
 * @retval      无
 */
void tim_int_callback_register(void (*callback)(void), uint16_t time)
{
    if (g_bitmx_callback_funs_num == 0)
    {
        btimx_int_init(CFG_TIM_INT_ID, CFG_TIM_INT_ARR, CFG_TIM_INT_PSC);
    }
    if (time < CFG_TIM_INT_PERIOD) // 如果时间小于定时器周期, 则不注册
    {
        DEBUG_ERROR("tim_int_callback_register: time < CFG_TIM_INT_PERIOD\r\n");
        return;
    }

    time /= CFG_TIM_INT_PERIOD; // 将时间转换为定时器计数值
    g_bitmx_callback_funs_time[g_bitmx_callback_funs_num] = time;
    g_timx_callback_funs[g_bitmx_callback_funs_num++] = callback;
}

/**
 * @brief       基本定时器TIMX定时中断回调函数注销
 * @param       callback: 定时器中断回调函数
 * @retval      无
 */
void tim_int_callback_deregister(void (*callback)(void))
{
    for (uint8_t i = 0; i < g_bitmx_callback_funs_num; i++)
    {
        if (g_timx_callback_funs[i] == callback)
        {
            for (uint8_t j = i; j < g_bitmx_callback_funs_num - 1; j++)
            {
                g_timx_callback_funs[j] = g_timx_callback_funs[j + 1];
                g_bitmx_callback_funs_time[j] = g_bitmx_callback_funs_time[j + 1];
            }
            g_bitmx_callback_funs_num--;
            break;
        }
    }
}

void TIM6_DAC_IRQHandler(void)
{
    static uint16_t count = 0;
    if (TIM6->SR & 0x01) /* 检查更新中断 */
    {
        TIM6->SR &= ~0x01; /* 清除更新中断标志 */
        for (int i = 0; i < g_bitmx_callback_funs_num; i++)
        {
            if (count % g_bitmx_callback_funs_time[i] == 0)
            {
                if (g_timx_callback_funs[i] != NULL)
                    g_timx_callback_funs[i](); /* 执行回调函数 */
            }
        }
    }
    count++;
}

/**
 * @brief       定时器TIMX PWM输出引脚初始化
 * @param       tim_id: 定时器ID
 * @param       channel: 通道号, 1~4
 * @param       pin: GPIO引脚位置, PA0~PI15
 * @param       arr: 自动重装值
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void tim_pwm_pin_init(uint8_t tim_id, uint8_t channel, uint8_t pin, uint32_t arr, uint32_t psc)
{
    TIM_TypeDef *timx;
    if (tim_id == 1)
    {
        timx = TIM1;
        RCC->APB2ENR |= 1 < 0; // 使能TIM1时钟
    }
    else if (tim_id == 2)
    {
        timx = TIM2;
        RCC->APB1ENR |= 1 << 0; // 使能TIM2时钟
    }
    else if (tim_id == 3)
    {
        timx = TIM3;
        RCC->APB1ENR |= 1 << 1; // 使能TIM3时钟
    }
    else if (tim_id == 4)
    {
        timx = TIM4;
        RCC->APB1ENR |= 1 << 2; // 使能TIM4时钟
    }
    else if (tim_id == 5)
    {
        timx = TIM5;
        RCC->APB1ENR |= 1 << 3; // 使能TIM5时钟
    }
    else if (tim_id == 6)
    {
        timx = TIM6;
        RCC->APB1ENR |= 1 << 4; // 使能TIM6时钟
    }
    else if (tim_id == 7)
    {
        timx = TIM7;
        RCC->APB1ENR |= 1 << 5; // 使能TIM7时钟
    }
    else if (tim_id == 8)
    {
        timx = TIM8;
        RCC->APB2ENR |= 1 << 1; // 使能TIM8时钟
    }
    else if (tim_id == 9)
    {
        timx = TIM9;
        RCC->APB2ENR |= 1 << 16; // 使能TIM9时钟
    }
    else if (tim_id == 10)
    {
        timx = TIM10;
        RCC->APB2ENR |= 1 << 17; // 使能TIM10时钟
    }
    else if (tim_id == 11)
    {
        timx = TIM11;
        RCC->APB2ENR |= 1 << 18; // 使能TIM11时钟
    }
    else if (tim_id == 12)
    {
        timx = TIM12;
        RCC->APB1ENR |= 1 << 6; // 使能TIM12时钟
    }
    else if (tim_id == 13)
    {
        timx = TIM13;
        RCC->APB1ENR |= 1 << 7; // 使能TIM13时钟
    }
    else if (tim_id == 14)
    {
        timx = TIM14;
        RCC->APB1ENR |= 1 << 8; // 使能TIM14时钟
    }

    gpio_pin_init(pin, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_MID, GPIO_PUPD_PU);
    if (tim_id == 1 || tim_id == 2) // TIM1 and TIM8 use AF1
    {
        gpio_af_set(pin, 1);
    }
    else if (tim_id == 3 || tim_id == 4 || tim_id == 5) // Other TIMs use AF2
    {
        gpio_af_set(pin, 2);
    }
    else if (tim_id == 8 || tim_id == 9 || tim_id == 10 || tim_id == 11)
    {
        gpio_af_set(pin, 3);
    }
    else if (tim_id == 12 || tim_id == 13 || tim_id == 14)
    {
        gpio_af_set(pin, 4);
    }

    timx->ARR = arr;
    timx->PSC = psc; /* 设置预分频器  */
    timx->BDTR |= 1 << 15;
    /* 使能MOE位(仅TIM15/16/17 有此寄存器,必须设置MOE才能输出PWM), 其他通用定时器,
    这个寄存器是无效的, 所以设置/不设置并不影响结果, 为了兼容这里统一改成设置MOE位 */

    if (channel <= 2)
    {
        timx->CCMR1 |= 6 << (4 + 8 * (channel - 1)); /* CH1/2 PWM模式1 */
        timx->CCMR1 |= 1 << (3 + 8 * (channel - 1)); /* CH1/2 预装载使能 */
    }
    else if (channel <= 4)
    {
        timx->CCMR2 |= 6 << (4 + 8 * (channel - 3)); /* CH3/4 PWM模式1 */
        timx->CCMR2 |= 1 << (3 + 8 * (channel - 3)); /* CH3/4 预装载使能 */
    }

    timx->CCER |= 1 << (4 * (channel - 1));     /* OCy 输出使能 */
    timx->CCER |= 0 << (1 + 4 * (channel - 1)); /* OCy 高电平有效 */
    timx->CR1 |= 1 << 7;                        /* ARPE使能 */
    timx->CR1 |= 1 << 0;                        /* 使能定时器TIMX */
}

/**
 * @brief       设置定时器TIMX的PWM通道的CCR值
 * @param       tim_id: 定时器ID
 * @param       channel: 通道号, 1~4
 * @param       ccr: CCR值, 0~65535
 * @retval      无
 */
void tim_pwm_set_ccr(uint8_t tim_id, uint8_t channel, uint16_t ccr)
{
    TIM_TypeDef *timx;
    if (tim_id == 1)
        timx = TIM1;
    else if (tim_id == 2)
        timx = TIM2;
    else if (tim_id == 3)
        timx = TIM3;
    else if (tim_id == 4)
        timx = TIM4;
    else if (tim_id == 5)
        timx = TIM5;
    else if (tim_id == 6)
        timx = TIM6;
    else if (tim_id == 7)
        timx = TIM7;
    else if (tim_id == 8)
        timx = TIM8;
    else if (tim_id == 9)
        timx = TIM9;
    else if (tim_id == 10)
        timx = TIM10;
    else if (tim_id == 11)
        timx = TIM11;
    else if (tim_id == 12)
        timx = TIM12;
    else if (tim_id == 13)
        timx = TIM13;
    else if (tim_id == 14)
        timx = TIM14;

    if (channel == 1)
    {
        timx->CCR1 = ccr; /* 设置CH1/2 CCR */
    }
    else if (channel == 2)
    {
        timx->CCR2 = ccr; /* 设置CH1/2 CCR */
    }
    else if (channel == 3)
    {
        timx->CCR3 = ccr; /* 设置CH3/4 CCR */
    }
    else if (channel == 4)
    {
        timx->CCR4 = ccr; /* 设置CH3/4 CCR */
    }
}

/**
 * @brief       初始化定时器TIMX的脉冲计数
 * @param       tim_id: 定时器ID
 * @param       channel: 通道号, 1~4
 * @param       pin: 脉冲计数引脚
 * @param       mode: 脉冲计数模式, 0: 脉冲计数, 1: 编码器计数模式3
 * @retval      无
 */
void tim_cnt_pin_init(uint8_t tim_id, uint8_t channel, uint8_t pin, uint8_t mode)
{
    TIM_TypeDef *timx;

    if (tim_id == 1)
    {
        timx = TIM1;
        RCC->APB2ENR |= 1 << 0; // 使能TIM1时钟
    }
    else if (tim_id == 2)
    {
        timx = TIM2;
        RCC->APB1ENR |= 1 << 0; // 使能TIM2时钟
    }
    else if (tim_id == 3)
    {
        timx = TIM3;
        RCC->APB1ENR |= 1 << 1; // 使能TIM3时钟
    }
    else if (tim_id == 4)
    {
        timx = TIM4;
        RCC->APB1ENR |= 1 << 2; // 使能TIM4时钟
    }
    else if (tim_id == 5)
    {
        timx = TIM5;
        RCC->APB1ENR |= 1 << 3; // 使能TIM5时钟
    }
    else if (tim_id == 6)
    {
        timx = TIM6;
        RCC->APB1ENR |= 1 << 4; // 使能TIM6时钟
    }
    else if (tim_id == 7)
    {
        timx = TIM7;
        RCC->APB1ENR |= 1 << 5; // 使能TIM7时钟
    }
    else if (tim_id == 8)
    {
        timx = TIM8;
        RCC->APB2ENR |= 1 << 1; // 使能TIM8时钟
    }
    else if (tim_id == 9)
    {
        timx = TIM9;
        RCC->APB2ENR |= 1 << 16; // 使能TIM9时钟
    }
    else if (tim_id == 10)
    {
        timx = TIM10;
        RCC->APB2ENR |= 1 << 17; // 使能TIM10时钟
    }
    else if (tim_id == 11)
    {
        timx = TIM11;
        RCC->APB2ENR |= 1 << 18; // 使能TIM11时钟
    }
    else if (tim_id == 12)
    {
        timx = TIM12;
        RCC->APB1ENR |= 1 << 6; // 使能TIM12时钟
    }
    else if (tim_id == 13)
    {
        timx = TIM13;
        RCC->APB1ENR |= 1 << 7; // 使能TIM13时钟
    }
    else if (tim_id == 14)
    {
        timx = TIM14;
        RCC->APB1ENR |= 1 << 8; // 使能TIM14时钟
    }

    gpio_pin_init(pin, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_HIGH, GPIO_PUPD_PD);

    if (tim_id == 1 || tim_id == 2) // TIM1 and TIM8 use AF1
    {
        gpio_af_set(pin, 1);
    }
    else if (tim_id == 3 || tim_id == 4 || tim_id == 5) // Other TIMs use AF2
    {
        gpio_af_set(pin, 2);
    }
    else if (tim_id == 8 || tim_id == 9 || tim_id == 10 || tim_id == 11)
    {
        gpio_af_set(pin, 3);
    }
    else if (tim_id == 12 || tim_id == 13 || tim_id == 14)
    {
        gpio_af_set(pin, 4);
    }

    timx->ARR = 65535; /* 设定计数器自动重装值为最大 */
    timx->PSC = 0;     /* 设置预分频器  */

    timx->CCMR1 |= 1 << 8 * (channel - 1);       /* CCyS[1:0]   = 01 选择输入端 IC1/2映射到TI1/2上 */
    timx->CCMR1 |= 0 << (2 + 8 * (channel - 1)); /* ICyPSC[1:0] = 00 输入捕获不分频,全捕获 */
    timx->CCMR1 |= 0 << (4 + 8 * (channel - 1)); /* ICyF[3:0]   = 00 输入端滤波 不滤波 */

    timx->CCER |= 1 << (4 * (channel - 1));     /* CCyE = 1 输入捕获使能 */
    timx->CCER |= 0 << (1 + 4 * (channel - 1)); /* CCyP = 0 捕获上升沿,即上升沿计数 ,注意:CCyNP使用默认值0 */

    timx->SMCR |= (4 + channel) << 4; /* TS[4:0] = 5/6  触发选择: 5,TI1FP1(TIMX_CH1);  6,TI2FP2(TIMX_CH2); */

    if (mode == 0)            // 脉冲计数模式
        timx->SMCR |= 7 << 0; /* SMS[2:0] = 7   外部时钟模式 1 */
    else if (mode == 1)       // 编码器计数模式
        timx->SMCR |= 3 << 0; /* SMS[2:0] = 3   编码器模式 3 */

    timx->EGR |= 1 << 0; /* 软件控制产生更新事件,使写入PSC的值立即生效,否则将会要等到定时器溢出才会生效 */
    timx->CR1 |= 1 << 0; /* 使能定时器TIMX */

    tim_cnt_set_value(tim_id, 0); /* 设置计数器初始值为0 */
}

/**
 * @brief       获取定时器TIMX的计数器值
 * @param       tim_id: 定时器ID
 * @retval      返回计数器值
 */
int32_t tim_cnt_get_value(uint8_t tim_id)
{
    TIM_TypeDef *timx;
    if (tim_id == 1)
        timx = TIM1;
    else if (tim_id == 2)
        timx = TIM2;
    else if (tim_id == 3)
        timx = TIM3;
    else if (tim_id == 4)
        timx = TIM4;
    else if (tim_id == 5)
        timx = TIM5;
    else if (tim_id == 6)
        timx = TIM6;
    else if (tim_id == 7)
        timx = TIM7;
    else if (tim_id == 8)
        timx = TIM8;
    else if (tim_id == 9)
        timx = TIM9;
    else if (tim_id == 10)
        timx = TIM10;
    else if (tim_id == 11)
        timx = TIM11;
    else if (tim_id == 12)
        timx = TIM12;
    else if (tim_id == 13)
        timx = TIM13;
    else if (tim_id == 14)
        timx = TIM14;

    return timx->CNT; /* 返回计数器值 */
}

/**
 * @brief       设置定时器TIMX的计数器值
 * @param       tim_id: 定时器ID
 * @param       value: 要设置的计数器值
 * @retval      无
 */
void tim_cnt_set_value(uint8_t tim_id, uint32_t value)
{
    TIM_TypeDef *timx;
    if (tim_id == 1)
        timx = TIM1;
    else if (tim_id == 2)
        timx = TIM2;
    else if (tim_id == 3)
        timx = TIM3;
    else if (tim_id == 4)
        timx = TIM4;
    else if (tim_id == 5)
        timx = TIM5;
    else if (tim_id == 6)
        timx = TIM6;
    else if (tim_id == 7)
        timx = TIM7;
    else if (tim_id == 8)
        timx = TIM8;
    else if (tim_id == 9)
        timx = TIM9;
    else if (tim_id == 10)
        timx = TIM10;
    else if (tim_id == 11)
        timx = TIM11;
    else if (tim_id == 12)
        timx = TIM12;
    else if (tim_id == 13)
        timx = TIM13;
    else if (tim_id == 14)
        timx = TIM14;

    timx->CNT = value; /* 设置计数器值 */
}
/* 输入捕获状态(g_timxchy_cap_sta[tim_id])
 * [7]  :0,没有成功的捕获;1,成功捕获到一次.
 * [6]  :0,还没捕获到高电平;1,已经捕获到高电平了.
 * [5:0]:捕获高电平后溢出的次数,最多溢出63次,所以最长捕获值 = 63*65536 + 65535 = 4194303
 *       注意:为了通用,我们默认ARR和CCRy都是16位寄存器,对于32位的定时器(如:TIM5),也只按16位使用
 *       按1us的计数频率,最长溢出时间为:4194303 us, 约4.19秒
 */
uint8_t g_timxchy_cap_sta[15] = {0};     /* 输入捕获状态 */
uint8_t g_timxchy_cap_channel[15] = {0}; /* 输入捕获通道 */
uint32_t g_timxchy_cap_val[15] = {0};    /* 输入捕获值 */
uint8_t g_timxchy_cap_en[15] = {0};      /* 输入捕获使能 */

/**
 * @brief       定时器TIMX输入捕获引脚初始化
 * @param       tim_id: 定时器ID
 * @param       channel: 通道号, 1~4
 * @param       pin: GPIO引脚位置, PA0~PI15
 * @param       arr: 自动重装值
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void tim_cap_pin_init(uint8_t tim_id, uint8_t channel, uint8_t pin, uint16_t arr, uint16_t psc)
{
    TIM_TypeDef *timx;
    uint8_t irqn;
    if (tim_id == 1)
    {
        timx = TIM1;
        RCC->APB2ENR |= 1 < 0; // 使能TIM1时钟
        irqn = TIM1_CC_IRQn;   // TIM1 is often used for input capture
    }
    else if (tim_id == 2)
    {
        timx = TIM2;
        RCC->APB1ENR |= 1 << 0; // 使能TIM2时钟
        irqn = TIM2_IRQn;
    }
    else if (tim_id == 3)
    {
        timx = TIM3;
        RCC->APB1ENR |= 1 << 1; // 使能TIM3时钟
        irqn = TIM3_IRQn;
    }
    else if (tim_id == 4)
    {
        timx = TIM4;
        RCC->APB1ENR |= 1 << 2; // 使能TIM4时钟
        irqn = TIM4_IRQn;
    }
    else if (tim_id == 5)
    {
        timx = TIM5;
        RCC->APB1ENR |= 1 << 3; // 使能TIM5时钟
        irqn = TIM5_IRQn;
    }
    else if (tim_id == 6)
    {
        timx = TIM6;
        RCC->APB1ENR |= 1 << 4; // 使能TIM6时钟
        irqn = TIM6_DAC_IRQn;   // TIM6 is often used for DAC, but can be used for general purposes
    }
    else if (tim_id == 7)
    {
        timx = TIM7;
        RCC->APB1ENR |= 1 << 5; // 使能TIM7时钟
        irqn = TIM7_IRQn;
    }
    else if (tim_id == 8)
    {
        timx = TIM8;
        RCC->APB2ENR |= 1 << 1; // 使能TIM8时钟
        irqn = TIM8_CC_IRQn;    // TIM8 is often used for input capture
    }
    else if (tim_id == 9)
    {
        timx = TIM9;
        RCC->APB2ENR |= 1 << 16;   // 使能TIM9时钟
        irqn = TIM1_BRK_TIM9_IRQn; // TIM9 is often used for input capture
    }
    else if (tim_id == 10)
    {
        timx = TIM10;
        RCC->APB2ENR |= 1 << 17;   // 使能TIM10时钟
        irqn = TIM1_UP_TIM10_IRQn; // TIM10 is often used for input capture
    }
    else if (tim_id == 11)
    {
        timx = TIM11;
        RCC->APB2ENR |= 1 << 18;        // 使能TIM11时钟
        irqn = TIM1_TRG_COM_TIM11_IRQn; // TIM11 is often used for input capture
    }
    else if (tim_id == 12)
    {
        timx = TIM12;
        RCC->APB1ENR |= 1 << 6;     // 使能TIM12时钟
        irqn = TIM8_BRK_TIM12_IRQn; // TIM12 is often used for input capture
    }
    else if (tim_id == 13)
    {
        timx = TIM13;
        RCC->APB1ENR |= 1 << 7;    // 使能TIM13时钟
        irqn = TIM8_UP_TIM13_IRQn; // TIM13 is often used for input capture
    }
    else if (tim_id == 14)
    {
        timx = TIM14;
        RCC->APB1ENR |= 1 << 8;         // 使能TIM14时钟
        irqn = TIM8_TRG_COM_TIM14_IRQn; // TIM14 is often used for input capture
    }
    g_timxchy_cap_en[tim_id] = 1;            /* 设置输入捕获使能标志 */
    g_timxchy_cap_channel[tim_id] = channel; /* 设置输入捕获通道 */
    gpio_pin_init(pin, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_HIGH, GPIO_PUPD_PD);
    if (tim_id == 1 || tim_id == 2) // TIM1 and TIM8 use AF1
    {
        gpio_af_set(pin, 1);
    }
    else if (tim_id == 3 || tim_id == 4 || tim_id == 5) // Other TIMs use AF2
    {
        gpio_af_set(pin, 2);
    }
    else if (tim_id == 8 || tim_id == 9 || tim_id == 10 || tim_id == 11)
    {
        gpio_af_set(pin, 3);
    }
    else if (tim_id == 12 || tim_id == 13 || tim_id == 14)
    {
        gpio_af_set(pin, 4);
    }

    timx->ARR = arr; /* 设定计数器自动重装值 */
    timx->PSC = psc; /* 设置预分频器  */

    if (channel <= 2)
    {
        timx->CCMR1 |= 1 << 8 * (channel - 1);       /* CCyS[1:0]   = 01 选择输入端 IC1/2映射到TI1/2上 */
        timx->CCMR1 |= 0 << (2 + 8 * (channel - 1)); /* ICyPSC[1:0] = 00 输入捕获不分频,全捕获 */
        timx->CCMR1 |= 0 << (4 + 8 * (channel - 1)); /* ICyF[3:0]   = 00 输入端滤波 不滤波 */
    }
    else if (channel <= 4)
    {
        timx->CCMR2 |= 1 << 8 * (channel - 3);       /* CCyS[1:0]   = 01 选择输入端 IC3/4映射到TI3/4上 */
        timx->CCMR2 |= 0 << (2 + 8 * (channel - 3)); /* ICyPSC[1:0] = 00 输入捕获不分频,全捕获 */
        timx->CCMR2 |= 0 << (4 + 8 * (channel - 3)); /* ICyF[3:0]   = 00 输入端滤波 不滤波 */
    }

    timx->CCER |= 1 << (4 * (channel - 1));     /* CCyE = 1 输入捕获使能 */
    timx->CCER |= 0 << (1 + 4 * (channel - 1)); /* CCyP = 0 捕获上升沿 ,注意:CCyNP使用默认值0 */

    timx->EGR |= 1 << 0;  /* 软件控制产生更新事件,使写入PSC的值立即生效,否则将会要等到定时器溢出才会生效 */
    timx->DIER |= 1 << 1; /* 允许捕获中断 */
    timx->DIER |= 1 << 0; /* 允许更新中断 */
    timx->CR1 |= 1 << 0;  /* 使能定时器TIMX */

    sys_nvic_init(1, 3, irqn, 2); /* 抢占1，子优先级3，组2 */
}

/**
 * @brief       定时器TIMX输入捕获中断回调函数
 * @param       tim_id: 定时器ID
 * @retval      无
 */
static void tim_cap_irq_callback(uint8_t tim_id)
{
    TIM_TypeDef *timx;
    if (tim_id == 1)
        timx = TIM1;
    else if (tim_id == 2)
        timx = TIM2;
    else if (tim_id == 3)
        timx = TIM3;
    else if (tim_id == 4)
        timx = TIM4;
    else if (tim_id == 5)
        timx = TIM5;
    else if (tim_id == 6)
        timx = TIM6;
    else if (tim_id == 7)
        timx = TIM7;
    else if (tim_id == 8)
        timx = TIM8;
    else if (tim_id == 9)
        timx = TIM9;
    else if (tim_id == 10)
        timx = TIM10;
    else if (tim_id == 11)
        timx = TIM11;
    else if (tim_id == 12)
        timx = TIM12;
    else if (tim_id == 13)
        timx = TIM13;
    else if (tim_id == 14)
        timx = TIM14;

    uint16_t tsr = timx->SR;                     /* 获取中断状态 */
    uint8_t chy = g_timxchy_cap_channel[tim_id]; /* 需要捕获的通道 */

    if ((g_timxchy_cap_sta[tim_id] & 0X80) == 0) /* 还未成功捕获 */
    {
        if (tsr & (1 << 0)) /* 溢出中断 */
        {
            if (g_timxchy_cap_sta[tim_id] & 0X40) /* 已经捕获到高电平了 */
            {
                if ((g_timxchy_cap_sta[tim_id] & 0X3F) == 0X3F) /* 高电平太长了 */
                {
                    timx->CCER &= ~(1 << (1 + 4 * (chy - 1))); /* CCyP = 0 设置为上升沿捕获 */
                    g_timxchy_cap_sta[tim_id] |= 0X80;         /* 标记成功捕获了一次 */
                    g_timxchy_cap_val[tim_id] = 0XFFFF;
                }
                else /* 还可以累加高电平长度 */
                {
                    g_timxchy_cap_sta[tim_id]++;
                }
            }
        }

        if (tsr & (1 << chy)) /* 通道y 发生了捕获事件 */
        {
            if (g_timxchy_cap_sta[tim_id] & 0X40) /* 捕获到一个下降沿 */
            {
                g_timxchy_cap_sta[tim_id] |= 0X80;         /* 标记成功捕获到一次高电平脉宽 */
                g_timxchy_cap_val[tim_id] = timx->CCR1;    /* 获取当前的捕获值. */
                timx->CCER &= ~(1 << (1 + 4 * (chy - 1))); /* CCyP = 0 设置为上升沿捕获 */
            }
            else /* 还未开始,第一次捕获上升沿 */
            {
                g_timxchy_cap_val[tim_id] = 0;
                g_timxchy_cap_sta[tim_id] = 0X40;       /* 标记捕获到了上升沿 */
                timx->CNT = 0;                          /* 计数器清空 */
                timx->CCER |= 1 << (1 + 4 * (chy - 1)); /* CCyP = 1 设置为下降沿捕获 */
            }
        }
    }
    timx->SR = 0; /* 清除中断状态 */
}

/**
 * @brief       获取定时器TIMX捕获的高电平时间
 * @param       tim_id: 定时器ID
 * @retval      返回捕获的高电平时间, 单位为us
 */
uint32_t tim_cap_get_value(uint8_t tim_id)
{
    uint32_t temp = 0;
    if (g_timxchy_cap_sta[tim_id] & 0X80) /* 成功捕获到了一次高电平 */
    {
        temp = g_timxchy_cap_sta[tim_id] & 0X3F;
        temp *= 0xFFFF;                    /* 溢出时间总和 */
        temp += g_timxchy_cap_val[tim_id]; /* 得到总的高电平时间 */
        g_timxchy_cap_sta[tim_id] = 0;     /* 开启下一次捕获*/
    }
    return temp; /* 返回捕获的高电平时间 */
}

void TIM1_CC_IRQHandler(void)
{
    if (g_timxchy_cap_en[1] == 1)
        tim_cap_irq_callback(1); /* TIM1 输入捕获中断 */
}

void TIM2_IRQHandler(void)
{
    if (g_timxchy_cap_en[2] == 1)
        tim_cap_irq_callback(2); /* TIM2 输入捕获中断 */
}

void TIM3_IRQHandler(void)
{
    if (g_timxchy_cap_en[3] == 1)
        tim_cap_irq_callback(3); /* TIM3 输入捕获中断 */
}

void TIM5_IRQHandler(void)
{
    if (g_timxchy_cap_en[5] == 1)
        tim_cap_irq_callback(5); /* TIM5 输入捕获中断 */
}

void TIM8_CC_IRQHandler(void)
{
    if (g_timxchy_cap_en[8] == 1)
        tim_cap_irq_callback(8); /* TIM8 输入捕获中断 */
}

void TIM1_BRK_TIM9_IRQHandler(void)
{
    if (g_timxchy_cap_en[9] == 1)
        tim_cap_irq_callback(9); /* TIM9 输入捕获中断 */
}

void TIM1_UP_TIM10_IRQHandler(void)
{
    if (g_timxchy_cap_en[10] == 1)
        tim_cap_irq_callback(10); /* TIM10 输入捕获中断 */
}

void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
    if (g_timxchy_cap_en[11] == 1)
        tim_cap_irq_callback(11); /* TIM11 输入捕获中断 */
}

void TIM8_BRK_TIM12_IRQHandler(void)
{
    if (g_timxchy_cap_en[12] == 1)
        tim_cap_irq_callback(12); /* TIM12 输入捕获中断 */
}

void TIM8_UP_TIM13_IRQHandler(void)
{
    if (g_timxchy_cap_en[13] == 1)
        tim_cap_irq_callback(13); /* TIM13 输入捕获中断 */
}

void TIM8_TRG_COM_TIM14_IRQHandler(void)
{
    if (g_timxchy_cap_en[14] == 1)
        tim_cap_irq_callback(14); /* TIM14 输入捕获中断 */
}
